home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / xvisrc.zip / UNIX.C < prev    next >
C/C++ Source or Header  |  1992-07-28  |  21KB  |  982 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)unix.c    2.1 (Chris & John Downey) 7/29/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     unix.c
  14. * module function:
  15.     System interface routines for all versions of UNIX.
  16. * history:
  17.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  18.     Originally by Tim Thompson (twitch!tjt)
  19.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  20.     Heavily modified by Chris & John Downey
  21.  
  22. ***/
  23.  
  24. #include "xvi.h"
  25.  
  26. #ifndef SIGINT
  27. #   include <signal.h>        /* get signals for call_shell() */
  28. #endif
  29.  
  30. #ifdef    BSD
  31. #   include <sys/wait.h>    /* get wait stuff for call_shell() */
  32.     typedef    union wait Wait_t;
  33. #else
  34.     typedef    int Wait_t;
  35. #endif
  36.  
  37. /*
  38.  * CTRL is defined by sgtty.h (or by a file it includes)
  39.  * so we undefine it here to avoid conflicts with the
  40.  * version defined in "xvi.h".
  41.  */
  42. #undef    CTRL
  43.  
  44. #ifdef    sun
  45. #   ifndef TERMIOS
  46. #    define    TERMIOS
  47. #   endif
  48. #endif
  49.  
  50. #ifdef TERMIOS
  51. #   ifndef TERMIO
  52. #    define    TERMIO
  53. #   endif
  54. #endif
  55.  
  56. #ifdef    TERMIO
  57. #   ifdef    TERMIOS
  58. #    include <termios.h>
  59.    typedef struct termios    Termstate;
  60. #    define getstate(p)    ((void) tcgetattr(0, (p)))
  61. #    define setstate(p)    ((void) tcsetattr(0, TCSANOW, (p)))
  62. #    define w_setstate(p)    ((void) tcsetattr(0, TCSADRAIN, (p)))
  63. #   else    /* no TERMIOS */
  64. #    include <termio.h>
  65.    typedef struct termio    Termstate;
  66. #    define getstate(p)    ((void) ioctl(0,TCGETA,(char *)(p)))
  67. #    define setstate(p)    ((void) ioctl(0,TCSETA,(char *)(p)))
  68. #    define w_setstate(p)    ((void) ioctl(0,TCSETAW,(char *)(p)))
  69. #   endif    /* no TERMIOS */
  70.  
  71.     /*
  72.      * Table of line speeds ... exactly 16 long, and the CBAUD mask
  73.      * is 017 (i.e. 15) so we will never access outside the array.
  74.      */
  75.     short    speeds[] = {
  76.     /* B0 */    0,
  77.     /* B50 */    50,
  78.     /* B75 */    75,
  79.     /* B110 */    110,
  80.     /* B134 */    134,
  81.     /* B150 */    150,
  82.     /* B200 */    200,
  83.     /* B300 */    300,
  84.     /* B600 */    600,
  85.     /* B1200 */    1200,
  86.     /* B1800 */    1800,
  87.     /* B2400 */    2400,
  88.     /* B4800 */    4800,
  89.     /* B9600 */    9600,
  90.     /* EXTA */    19200,        /* not defined at V.2 */
  91.     /* EXTB */    38400,        /* not defined at V.2 */
  92.     };
  93.  
  94. #else    /* not TERMIO */
  95.  
  96. #   include <sgtty.h>
  97.     typedef struct sgttyb    Termstate;
  98.  
  99.     static    struct    tchars    ckd_tchars, raw_tchars;
  100.     static    struct    ltchars    ckd_ltchars, raw_ltchars;
  101.  
  102. #   ifdef FD_SET
  103. #    define    fd_set_type    fd_set
  104. #   else        /* FD_SET not defined */
  105.     /*
  106.      * BSD 4.2 doesn't have these macros.
  107.      */
  108.     typedef int fd_set_type;
  109. #    define    FD_ZERO(p)    (*(p) = 0)
  110. #    define    FD_SET(f,p)    (*(p) |= (1 << (f)))
  111. #   endif        /* FD_SET not defined */
  112. #endif    /* not TERMIO */
  113.  
  114. static    Termstate    cooked_state, raw_state;
  115.  
  116. #undef    CTRL
  117.  
  118. #ifdef    SETVBUF_AVAIL
  119.     /*
  120.      * Output buffer to save function calls.
  121.      */
  122.     static    char    outbuffer[128];
  123. #endif
  124.  
  125. #ifdef MEMTEST
  126. #   include <sys/resource.h>
  127. #endif        /* MEMTEST */
  128.  
  129. /*
  130.  * Expected for termcap's benefit.
  131.  */
  132. short        ospeed;            /* tty's baud rate */
  133.  
  134. /*
  135.  * We sometimes use a lot of system calls while trying to read from
  136.  * the keyboard; these are needed to make our automatic buffer
  137.  * preservation and input timeouts work properly. Nevertheless, it
  138.  * is possible that, with this much overhead, a reasonably fast typist
  139.  * could get ahead of us, so we do a small amount of input buffering
  140.  * to reduce the number of system calls.
  141.  *
  142.  * This variable gives the number of characters in the buffer.
  143.  */
  144. static int    kb_nchars;
  145.  
  146. /*
  147.  * Get a single byte from the keyboard.
  148.  *
  149.  * If the keyboard input buffer is empty, & read() fails or times out,
  150.  * return EOF.
  151.  */
  152. static int
  153. kbgetc()
  154. {
  155.     static unsigned char    kbuf[48];
  156.     static unsigned char    *kbp;
  157.  
  158.     if (kb_nchars <= 0) {
  159.     int nread;
  160.  
  161.     if ((nread = read(0, (char *) kbuf, sizeof kbuf)) <= 0) {
  162.         return EOF;
  163.     } else {
  164.         kb_nchars = nread;
  165.         kbp = kbuf;
  166.     }
  167.     }
  168.     --kb_nchars;
  169.     return(*kbp++);
  170. }
  171.  
  172. #ifdef TERMIO
  173.  
  174. /*
  175.  * Set a timeout on standard input. 0 means no timeout.
  176.  *
  177.  * This depends on raw_state having been properly initialized, which
  178.  * should have been done by sys_startv().
  179.  */
  180. static void
  181. input_timeout(msec)
  182. long    msec;
  183. {
  184.     int        vtime;
  185.     static int    lastvtime;
  186.  
  187.     /*
  188.      * If the device state hasn't been changed since last time, we
  189.      * don't need to do anything.
  190.      */
  191.     if ((vtime = (msec + 99) / 100) != lastvtime) {
  192.     lastvtime = vtime;
  193.     raw_state.c_cc[VMIN] = (vtime == 0 ? 1 : 0);
  194.     raw_state.c_cc[VTIME] = vtime;
  195.     setstate(&raw_state);
  196.     }
  197. }
  198.  
  199. #endif    /* TERMIO */
  200.  
  201. /*
  202.  * Get a character from the keyboard.
  203.  *
  204.  * Make sure screen is updated first.
  205.  */
  206. int
  207. inch(timeout)
  208. long    timeout;
  209. {
  210.     int        c;
  211.  
  212.     /*
  213.      * If we had characters left over from last time, return one.
  214.      *
  215.      * Note that if this happens, we don't call flush_output().
  216.      */
  217.     if (kb_nchars > 0) {
  218.     return(kbgetc());
  219.     }
  220.  
  221.     /*
  222.      * Need to get a character. First, flush output to the screen.
  223.      */
  224.     flush_output();
  225.  
  226. #ifdef TERMIO
  227.     if (timeout != 0) {
  228.     input_timeout(timeout);
  229.     c = kbgetc();
  230.     input_timeout(0L);
  231.     return(c);
  232.     }
  233. #else    /* no TERMIO */
  234.     if (timeout != 0) {
  235.     struct timeval    tv;
  236.     fd_set_type    readfds;
  237.  
  238.     tv.tv_sec = (long) (timeout / 1000);
  239.     tv.tv_usec = ((long) timeout * 1000) % (long) 1000000;
  240.  
  241.     FD_ZERO(&readfds);
  242.     FD_SET(0, &readfds);
  243.  
  244.     /*
  245.      * If select does not return 0, some input is available
  246.      * (ignoring the possibility of errors). Otherwise, we
  247.      * timed out, so return EOF.
  248.      */
  249.     if (select(1, &readfds, (fd_set_type *) NULL,
  250.             (fd_set_type *) NULL, &tv) == 0) {
  251.         return(EOF);
  252.     }
  253.     }
  254. #endif    /* no TERMIO */
  255.  
  256.     /*
  257.      * Keep trying until we get at least one character.
  258.      */
  259.     while ((c = kbgetc()) == EOF)
  260.     ;
  261.  
  262.     return(c);
  263. }
  264.  
  265. #if !(defined(__STDC__) || (defined(ultrix) && defined(mips)))
  266. /*
  267.  * If we have ANSI C, we should have strerror() anyway. Also, Ultrix
  268.  * on DECStations provides it.
  269.  */
  270. const char *
  271. strerror(err)
  272. int    err;
  273. {
  274.     extern char    *sys_errlist[];
  275.     extern int    sys_nerr;
  276.  
  277.     return(
  278.     err == 0 ?
  279.         "No error"
  280.         :
  281.         (err > 0 && err < sys_nerr) ?
  282.         sys_errlist[err]
  283.         :
  284.         "Unknown error"
  285.     );
  286. }
  287.  
  288. #endif /* !(defined(__STDC__) || (defined(ultrix) && defined(mips))) */
  289.  
  290. static int
  291. runvp(args)
  292. char    **args;
  293. {
  294.     int        pid;
  295.     Wait_t    status;
  296.  
  297.     pid = fork();
  298.     switch (pid) {
  299.     case -1:        /* fork() failed */
  300.     return(-1);
  301.  
  302.     case 0:            /* this is the child */
  303.     (void) signal(SIGINT, SIG_DFL);
  304.     (void) signal(SIGQUIT, SIG_DFL);
  305.     (void) execvp(args[0], args);
  306.  
  307.     /*
  308.      * Couldn't do it ... use standard output functions here
  309.      * because none of xvi's higher-level functions are usable
  310.      * from this module.
  311.      */
  312.     (void) fputs("\007Can't execute ", stdout);
  313.     (void) fputs(args[0], stdout);
  314.     (void) fputs("\n(", stdout);
  315.     (void) fputs(strerror(errno), stdout);
  316.     (void) fputs(")\nHit return to continue", stdout);
  317.     (void) fflush(stdout);
  318.     (void) getc(stdin);
  319.     exit(1);
  320.  
  321.     default:        /* this is the parent */
  322.     while (wait(&status) != pid)
  323.         ;
  324.     return(0);
  325.     }
  326. }
  327.  
  328. int
  329. call_shell(sh)
  330. char    *sh;
  331. {
  332.     static char    *args[] = { NULL, NULL };
  333.  
  334.     args[0] = sh;
  335.     return(runvp(args));
  336. }
  337.  
  338. int
  339. call_system(command)
  340. char    *command;
  341. {
  342.     static char    *args[] = { NULL, "-c", NULL, NULL };
  343.  
  344.     if (Ps(P_shell) == NULL) {
  345.     (void) puts("\007Can't execute command without SHELL parameter");
  346.     return(-1);
  347.     }
  348.     args[0] = Ps(P_shell);
  349.     args[2] = command;
  350.     return(runvp(args));
  351. }
  352.  
  353. #ifdef ITIMER_REAL
  354.     static int
  355.     nothing()
  356.     {
  357.     return(0);
  358.     }
  359. #endif
  360.  
  361. /*
  362.  * Delay for a short time - preferably less than 1 second.
  363.  * This is for use by showmatch, which wants to hold the
  364.  * cursor over the matching bracket for just long enough
  365.  * that it will be seen.
  366.  */
  367. void
  368. delay()
  369. {
  370. #ifdef ITIMER_REAL
  371.     struct itimerval    timer;
  372.     
  373.     (void) signal(SIGALRM, nothing);
  374.  
  375.     /*
  376.      * We want to pause for 200 msec (1/5th of a second) here,
  377.      * as this seems like a reasonable figure. Note that we can
  378.      * assume that the implementation will have defined tv_usec
  379.      * of a type large enough to hold up to 999999, since that's
  380.      * the largest number of microseconds we can possibly need.
  381.      */
  382.     timer.it_interval.tv_sec = 0;
  383.     timer.it_interval.tv_usec = 0;
  384.     timer.it_value.tv_sec = 0;
  385.     timer.